import Router from '@koa/router';
import db from '../mysqlHelper.js';
import logger from '../logger.js';
import response from '../response.js';

import { DEVICES } from "../publicValue.js";
import moment from 'moment';
import fs, { write } from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';

const router = new Router;
router.prefix('/api');
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);


router.post('/device/readParam', async (ctx) => {
    let body = ctx.request.body;
    if (body == null) {
        ctx.body = response.fail("参数不允许为空");
        return;
    }
    if (body.sn == null) {
        ctx.body = response.fail("缺少必填字段 sn");
        return;
    }
    let device = DEVICES.get(body.sn);
    if (device == null) {
        ctx.body = response.fail("设备不存在");
        return;
    }
    let result = await device.readParam();
    // ctx.body = response.success(result);
    console.log('获取参数返回：', JSON.stringify(result));
    if (result.code == 0) {
        ctx.body = response.fail(result.err);
        return;
    } else {
        ctx.body = response.success(result);
        return;
    }

});
router.post('/device/writeParam', async (ctx) => {
    let body = ctx.request.body;
    if (body == null) {
        ctx.body = response.fail("参数不允许为空");
        return;
    }
    if (body.sn == null) {
        ctx.body = response.fail("缺少必填字段 sn");
        return;
    }
    if (body.addr == null) {
        ctx.body = response.fail("缺少必填字段 addr");
        return;
    }
    if (body.value == null) {
        ctx.body = response.fail("缺少必填字段 value");
        return;
    }
    let device = DEVICES.get(body.sn);
    if (device == null) {
        ctx.body = response.fail("设备不存在");
        return;
    }
    let values = [];
    //检查body.value是否为数组
    if (!Array.isArray(body.value)) {
        values.push(parseFloat(body.value));
    }
    else {
        for (const item of body.value) {
            values.push(parseFloat(item));
        }
    }

    let result = await device.writeParam(body.addr, values);
    console.log('写入参数返回：', JSON.stringify(result));
    if (!result.code) {
        ctx.body = response.fail("写入参数失败");
        return;
    }
    if (result.code == 0) {
        ctx.body = response.fail(result.err);
        return;
    } else {
        ctx.body = response.success();
        return;
    }
});
router.post('/device/readRealData', async (ctx) => {
    let body = ctx.request.body;
    if (body == null) {
        ctx.body = response.fail("参数不允许为空");
        return;
    }
    if (body.sn == null) {
        ctx.body = response.fail("缺少必填字段 sn");
        return;
    }
    let device = DEVICES.get(body.sn);
    if (device == null) {
        ctx.body = response.fail("设备不存在");
        return;
    }
    let result = await device.readRealData();
    console.log('获取实时数据返回：', JSON.stringify(result));
    if (result.code == 0) {
        ctx.body = response.fail(result.err);
        return;
    } else {
        ctx.body = response.success(result);
        return;
    }
});
router.post('/device/recharge', async (ctx) => {
    let body = ctx.request.body;
    //获取token中的操作员id
    let oper = ctx.state.oper;
    let db_oper = await db.findOne('oper', { account: oper.account });
    if (db_oper == null) {
        ctx.body = response.fail("操作员不存在");
        return;
    }
    body.oper_name = db_oper.name;
    if (body == null) {
        ctx.body = response.fail("参数不允许为空");
        return;
    }
    if (body.sn == null) {
        ctx.body = response.fail("缺少必填字段 sn");
        return;
    }
    if (body.price == null) {
        ctx.body = response.fail("缺少必填字段 price");
        return;
    }
    if (body.amount == null) {
        ctx.body = response.fail("缺少必填字段 amount");
        return;
    }
    let changeValue = body.amount / body.price;
    //将changeValue向上取整保留3位小数
    changeValue = Math.ceil(changeValue * 1000) / 1000;


    let device = DEVICES.get(body.sn);
    if (device == null) {
        ctx.body = response.fail("设备不存在");
        return;

    }
    let result = await device.recharge(changeValue);
    console.log('充值返回：', JSON.stringify(result));

    if (result.code == 0) {
        ctx.body = response.fail(result.err);
        return;
    } else {
        let chargeRecord = {
            sn: body.sn,
            pay_type: 0,//0:现金 1:移动支付
            oper_name: body.oper_name,
            amount: body.amount,
            balance: result.balance,
            c_balance: result.c_balance,
            price: body.price,
            recharge: changeValue,
            project_id: body.project_id,
            enterprise_id: body.enterprise_id,
            device_name: body.device_name,
            write_time: moment().format('YYYY-MM-DD HH:mm:ss'),
            oper_time: moment().format('YYYY-MM-DD HH:mm:ss'),
            write_status: 1,
        };
        let res = await db.create('recharge', chargeRecord);
        if (res instanceof Error) {
            console.error('充值记录写入失败', res.message, JSON.stringify(chargeRecord));
            ctx.body = response.fail('充值失败，记录写入失败,失败原因:' + res.message);
            return;
        }
        delete result.code;
        console.log('充值响应：', JSON.stringify(result));
        ctx.body = response.success(result);

        return;
    }
});

router.post('/device/customerRecharge', async (ctx) => {
    let body = ctx.request.body;
    //获取token中的操作员id
    let oper = ctx.state.oper;
    let db_oper = await db.findOne('oper', { account: oper.account });
    if (db_oper == null) {
        ctx.body = response.fail("操作员不存在");
        return;
    }
    body.oper_name = db_oper.name;
    if (body == null) {
        ctx.body = response.fail("参数不允许为空");
        return;
    }
    if (body.sn == null) {
        ctx.body = response.fail("缺少必填字段 sn");
        return;
    }
    if(body.changeValue == null){
        ctx.body = response.fail("缺少必填字段 changeValue");
        return;
    }
    let device = DEVICES.get(body.sn);
    if (device == null) {
        ctx.body = response.fail("设备不存在");
        return;
    }
    let result = await device.recharge(body.changeValue);
    console.log(`操作员${ body.oper_name} 自定义充值  充值数据${body.changeValue} 充值返回：`, JSON.stringify(result));
    if (result.code == 0) {
        ctx.body = response.fail(result.err);
        return;
    }
    ctx.body = response.success(result);
    return;
});

router.post('/device/chargePrice', async (ctx) => {
    let body = ctx.request.body;
    //获取token中的操作员id
    let oper = ctx.state.oper;
    let db_oper = await db.findOne('oper', { account: oper.account });
    if (db_oper == null) {
        ctx.body = response.fail("操作员不存在");
        return;
    }
    body.oper_name = db_oper.name;
    if (body == null) {
        ctx.body = response.fail("参数不允许为空");
        return;
    }
    if (body.sn == null) {
        ctx.body = response.fail("缺少必填字段 sn");
        return;
    }
    if (body.price == null) {
        ctx.body = response.fail("缺少必填字段 price");
        return;
    }

    let device = DEVICES.get(body.sn);
    if (device == null) {
        ctx.body = response.fail("设备不存在");
        return;
    }

    let result = await device.changePrice(body.price);
    console.log('修改价格返回：', JSON.stringify(result));
    if (result.code == 0) {
        ctx.body = response.fail(result.err);
        return;
    } else {
        ctx.body = response.success();
        return;
    }
});

router.post('/device/readBlance', async (ctx) => {
    let body = ctx.request.body;
    if (body == null) {
        ctx.body = response.fail("参数不允许为空");
        return;
    }
    if (body.sn == null) {
        ctx.body = response.fail("缺少必填字段 sn");
        return;
    }
    let device = DEVICES.get(body.sn);
    if (device == null) {
        ctx.body = response.fail("设备不存在");
        return;
    }
    let result = await device.readBlance();

    console.log('获取余额返回：', JSON.stringify(result));
    if (result.code == 0) {
        ctx.body = response.fail(result.err);
        return;
    } else {
        ctx.body = response.success(result.data);
        return;
    }
});


router.post('/device/queryOnLine', async (ctx) => {
    let body = ctx.request.body;
    if (body == null) {
        ctx.body = response.fail("参数不允许为空");
        return;
    }
    if (body.enterprise_id == null && body.project_id == null) {
        ctx.body = response.fail("缺少必填字段 enterprise_id 或 project_id");
        return;
    }
    if (body.enterprise_id != null) {
        //查询企业下在线和不在线的设备数量
        let sql = `SELECT is_online,COUNT(*) as count FROM device WHERE enterprise_id = ? GROUP BY is_online`;
        let result = await db.query(sql, [body.enterprise_id]);
        if (result instanceof Error) {
            console.error('查询设备在线状态失败', result.message);
            ctx.body = response.fail('查询设备在线状态失败');
            return;
        }
        let online = 0;
        let offline = 0;
        for (const item of result) {
            if (item.is_online == 1) {
                online = item.count;
            } else {
                offline = item.count + offline;
            }
        }
        ctx.body = response.success({ online, offline });
        return;
    } else if (body.project_id != null) {
        //查询项目下在线和不在线的设备数量
        let sql = `SELECT is_online,COUNT(*) as count FROM device WHERE project_id = ? GROUP BY is_online`;
        let result = await db.query(sql, [body.project_id]);
        if (result instanceof Error) {
            console.error('查询设备在线状态失败', result.message);
            ctx.body = response.fail('查询设备在线状态失败');
            return;
        }
        let online = 0;
        let offline = 0;
        for (const item of result) {
            if (item.is_online == 1) {
                online = item.count;
            } else {
                offline = item.count + offline;
            }
        }
        ctx.body = response.success({ online, offline });
        return;
    }
});

async function mkdirsSync(dirname) {
    if (fs.existsSync(dirname)) {
        return true;
    } else {
        if (mkdirsSync(path.dirname(dirname))) {
            fs.mkdirSync(dirname);
            return true;
        }
    }
}

//上传图片到软件根目录下/View/images
router.post('/project/uploadImage', async (ctx) => {
    if (!ctx.request.files && !ctx.request.files.file) {
        ctx.status = 400;
        ctx.body = response.fail('No file uploaded');
        return;
    }

    let file = ctx.request.files.file;
    let reader = fs.createReadStream(file.filepath);

    let targetPath = path.join(__dirname, '../View/images/', file.originalFilename);
    let targetDir = path.dirname(targetPath);

    let res = await mkdirsSync(targetDir);
    if (!res) {
        ctx.body = response.fail('Failed to create directory');
        return;
    }
    let writer = fs.createWriteStream(targetPath);
    reader.pipe(writer);

    // 监听文件写入完成
    writer.on('finish', () => {
        console.log('File upload completed');
    });

    // 错误处理
    writer.on('error', (err) => {
        console.error('File upload failed:', err);
        ctx.status = 500;
        ctx.body = response.fail('File upload failed');
    });

    ctx.body = response.success({ url: `/images/${file.originalFilename}` });





});


router.post('/device/historySum', async (ctx) => {
    let body = ctx.request.body;
    if (body == null) {
        ctx.body = response.fail("参数不允许为空");
        return;
    }
    if (body.start_time == null) {
        ctx.body = response.fail("缺少必填字段 start_time");
        return;
    }
    if (body.end_time == null) {
        ctx.body = response.fail("缺少必填字段 end_time");
        return;
    }
    let deviceSql = 'SELECT sn, name FROM device';
    if (body.enterprise_id != null && body.enterprise_id != "") {
        deviceSql = `SELECT sn, name FROM device WHERE enterprise_id = ${body.enterprise_id}`;
    }
    if (body.project_id != null && body.project_id != "") {
        deviceSql = `SELECT sn, name FROM device WHERE project_id = ${body.project_id}`;
    }

    let sns = '';
    let deviceMap = new Map();
    let devices = await db.query(deviceSql);
    if (devices instanceof Error) {
        console.error('查询设备失败', devices.message);
        ctx.body = response.fail('查询设备失败');
        return;
    }
    if (devices.length == 0) {
        ctx.body = response.success([]);
        return;
    }
    sns = 'and sn IN  (';
    for (const item of devices) {
        sns += `'${item.sn}',`;
        deviceMap.set(item.sn, item.name);
    }
    sns = sns.substr(0, sns.length - 1);
    sns += ')';
    let sql = `WITH RankedRecords AS (
    SELECT
        sn,
        read_time,
        total_flow,
        ROW_NUMBER() OVER (PARTITION BY sn ORDER BY read_time ASC) AS rn_asc,
        ROW_NUMBER() OVER (PARTITION BY sn ORDER BY read_time DESC) AS rn_desc
    FROM history
    WHERE read_time BETWEEN '${body.start_time}' AND '${body.end_time}'  ${sns}
)
SELECT
    sn,
    MIN(CASE WHEN rn_asc = 1 THEN read_time END) AS start_read_time,
    MIN(CASE WHEN rn_asc = 1 THEN total_flow END) AS start_value,
    MIN(CASE WHEN rn_desc = 1 THEN read_time END) AS end_read_time,
    MIN(CASE WHEN rn_desc = 1 THEN total_flow END) AS end_value
FROM RankedRecords
GROUP BY sn;`
    let result = await db.query(sql);
    if (result instanceof Error) {
        console.error('查询历史数据失败', result.message);
        ctx.body = response.fail('查询历史数据失败');
        return;
    }

    // 将设备名称添加到结果中
    result = result.map(row => ({
        ...row,
        name: deviceMap.get(row.sn)
    }));

    ctx.body = response.success(result);
    return;
});


router.post('/DCS/GET/REALDATA', async (ctx) => {
    let body = ctx.request.body;
    let sn ='';
    if(body?.sn != null){
        sn = body.sn;
    }
    let sql ='select * from device';
    if(sn != ''){
        sql += ` where sn = '${sn}'`;
    }
    let devices = await db.query(sql);
    if (devices instanceof Error) {
        console.error('查询设备失败', devices.message);
        ctx.body = response.fail('查询设备失败');
        return;
    }
    ctx.body = response.success(devices);
    return;
});




export { router };